<?php
/***
 * Candy框架 XML操作类	
 * 
 * $Author: 刘森 (fingerboy@qq.com) $
 * $Date: 2019-08-05 01:28:06 $   
 */

namespace Candy\Extend\Str;

defined('CANDY') OR die('You Are A Bad Guy. o_O???');

final Class Xml {
	private static $xml = null;
	private static $_config = [];
	private static $elementArr = [];

	/**
	 * 配置
	 */
	private static function _config(): void
	{
		//初始化
		self::$xml = null;
		self::$elementArr = [];
		$element = ['version'=>'1.0', 'encoding'=>'UTF-8', 'root'=>'root'];
		$configfile = INCPATH.'xml.php';
		$_config = is_file($configfile) ? include($configfile) : [];
		$_config = array_merge($element, $_config);
		self::$_config = $_config;
	}
	
	/**
	 * 数组转变xml
	 *
	 * @param array $data 待转数组
	 */
	public static function arrayToXml(array $data): string
	{
		self::_config();
		self::startDocument();
		self::buildXml($data, false);
		if(defined('CLIWORKING')){
			\Workerman\Protocols\HttpCache::$header['Content-Type'] = 'Content-Type:text/xml; charset=utf-8';
		}else{
			header('Content-Type:text/xml; charset=utf-8');
		}
		return self::$xml;
	}
	
	/**
	 * xml转变数组
	 *
	 * @param string $xml xml数据
	 */
	public static function xmlToArray(string $xml): array
	{
		//禁止引用外部xml实体
		libxml_disable_entity_loader(true);
		$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
		$val = json_decode(json_encode($xmlstring),true);
		return $val;
	} 
	
	/**
	 * 创建xml
	 *
	 * @param array $data 数组
	 * @param bool $eIsArray 开头表示
	 */
	private static function buildXml(array $data,bool $eIsArray=false): void
	{
		if(!$eIsArray){
			self::startElement(self::$_config['root']);
		}
		foreach($data as $key => $value){
			if(is_numeric($key)){
				$key  = 'item';
			}
			if(is_array($value)){
				self::startElement($key);
				self::buildXml($value, TRUE);
				self::endElement();
				continue;
			}
			self::writeElement($key, $value);
		}
		if(!$eIsArray){
			self::endElement();
		}
	}
	
	/**
	 * 创建Element元素
	 *
	 * @param string $key 键
	 * @param string $value 值
	 */
	private static function writeElement(string $key,string $value): void
	{
		self::startElement($key);
		if(is_numeric($value)){
			self::$xml .= $value;
		}else{
			self::$xml .= '<![CDATA['.$value.']]>';
		}
		self::endElement();
	}

	/**
	 * 创建Element开始符
	 *
	 * @param string $element 头元素名称
	 */
	private static function startElement(string $element): void
	{
		self::$xml .= "<$element>";
		self::$elementArr[] = $element;
	}
	
	/**
	 * 创建Document标识
	 */
	private static function startDocument(): void
	{
		self::$xml .= '<?xml version="'. self::$_config['version'] .'" encoding="'. self::$_config['encoding'] .'"?>';
	}
	
	/**
	 * 创建Element结束符
	 */
	private static function endElement(): void
	{
		$element = array_pop(self::$elementArr);
		self::$xml .= "</$element>";
	}	
}
